package com.bjc.base.annotation.config;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URLDecoder;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.bjc.base.bean.request.BaseReqVO;
import com.bjc.base.core.MyException;
import com.bjc.base.core.annotation.Logical;
import com.bjc.base.core.annotation.Permission;
import com.bjc.core.bean.response.EmployeeVO;
import com.bjc.core.tool.service.IRedisService;

/**
 * 切面拦截器
 * 
 * @author 许自辉
 * @date 2017年8月11日
 */
@Aspect
//@Component
public class AnnotationAspect {

	@Autowired
	private IRedisService redisService;

	/**
	 * 拦截PostMapping 添加用户创建人id和用户更新人id
	 */
	@Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
	public void annotationPoinCutPost() {
	}

	/**
	 * 拦截PutMapping 添加用户更新人id
	 */
	@Pointcut("@annotation(org.springframework.web.bind.annotation.PutMapping)")
	public void annotationPoinCutPut() {
	}

	/**
	 * 拦截PutMapping 添加用户更新人id
	 */
	@Pointcut("@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
	public void annotationPoinCutDelete() {
	}

	/**
	 * 拦截PutMapping 添加用户更新人id
	 */
	@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
	public void annotationPoinCutGet() {
	}

	/**
	 * 拦截RequiresPermissions 注解权限
	 */
	@Pointcut("@annotation(com.bjc.base.core.annotation.Permission)")
	public void annotationPoinCut() {
	}

	@Before("annotationPoinCut()")
	public void after(JoinPoint joinPoint) throws UnsupportedEncodingException, MyException {
		EmployeeVO employeeVO = tokenValidate();
		String roles = employeeVO.getRoles();
		if (StringUtils.isNoneBlank(roles)) {
			throw new MyException("你没有任何角色！请找管理员配置角色");
		}

		String permissionCodes = employeeVO.getPermissionCodes();
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		Permission action = method.getDeclaredAnnotation(Permission.class);
		String[] values = action.value();

		/**
		 * 如果是系统管理员，默认拥有“查询角色”，“查询角色为拥有权限”，“查询角色已拥有权限”，“添加角色权限”，“删除角色权限”
		 * 以便项目初始化配置
		 */
		boolean systemAdminFlag = false;
		if (employeeVO.getRoles().contains("SystemAdmin") && (values[0].contains("role:findPage")
				|| values[0].contains("rolePermission:findTreeHave") || values[0].contains("rolePermission:createList")
				|| values[0].contains("rolePermission:deleteList"))) {
			systemAdminFlag = true;
		}

		final String noPermission =  "对不起,您没有该接口的权限!";
		if (!systemAdminFlag) {
			int length = values.length;
			if (length == 1) {
				if (!permissionCodes.contains(action.value()[0])) {
					throw new MyException(noPermission);
				}
			} else {
				if (action.logical().equals(Logical.AND)) {
					for (int i = 0; i < length; i++) {
						if (!permissionCodes.contains(action.value()[i])) {
							throw new MyException(noPermission);
						}
					}
				} else {
					boolean flag = false;
					for (int i = 0; i < length; i++) {
						if (permissionCodes.contains(action.value()[i])) {
							flag = true;
						}
					}
					if (!flag) {
						throw new MyException(noPermission);
					}
				}

			}
		}

	}

	@Before("annotationPoinCutPost() && execution(* com.bjc.**.controller.*.*(..))")
	public void afterPost(JoinPoint joinPoint) throws UnsupportedEncodingException, MyException {
		EmployeeVO employeeVO = tokenValidate();
		for (int i = 0; i < joinPoint.getArgs().length; i++) {
			Object object = joinPoint.getArgs()[i];
			if (object instanceof BaseReqVO) {
				BaseReqVO baseReqVO = (BaseReqVO) object;
				baseReqVO.setCreateBy(employeeVO.getWorkId());
				baseReqVO.setLastUpdateBy(employeeVO.getWorkId());
			}
		}

	}

	@Before("annotationPoinCutPut() && execution(* com.bjc.**.controller.*.*(..))")
	public void afterPut(JoinPoint joinPoint) throws UnsupportedEncodingException, MyException {
		EmployeeVO employeeVO = tokenValidate();
		for (int i = 0; i < joinPoint.getArgs().length; i++) {
			Object object = joinPoint.getArgs()[i];
			if (object instanceof BaseReqVO) {
				BaseReqVO baseReqVO = (BaseReqVO) object;
				baseReqVO.setLastUpdateBy(employeeVO.getWorkId());
			}
		}
	}

	@Before("annotationPoinCutDelete() && execution(* com.bjc.**.controller.*.*(..))")
	public void afterDelete(JoinPoint joinPoint) throws UnsupportedEncodingException, MyException {
		tokenValidate();
	}

	@Before("annotationPoinCutGet() && execution(* com.bjc.**.controller.*.*(..))")
	public void afterGet(JoinPoint joinPoint) throws UnsupportedEncodingException, MyException {
		tokenValidate();
	}

	private EmployeeVO tokenValidate() throws UnsupportedEncodingException, MyException {
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		String bjcToken = request.getHeader("bjcToken");
		if (StringUtils.isEmpty(bjcToken)) {
			throw new MyException("bjcToken不能为空");
		}
		String bjcTokens = URLDecoder.decode(bjcToken, "UTF-8");
		String user = redisService.get(bjcTokens);
		if (StringUtils.isNotEmpty(user)) {
			return JSON.parseObject(user, EmployeeVO.class);
		} else {
			throw new MyException("bjcToken失效，请重新登录！");
		}
	}

}
